﻿
Imports System.IO
Imports System.Net
Imports std
Imports xmlctrl
Imports xhtmlctrl

Public Module firstpage

    Public Const defaultConfigfile As String = "firstpage.ini"

    Public WithEvents config As configMonitor = Nothing
    Public WithEvents server As httpServer = Nothing
    Public responseBuffer As pool(Of MemoryStream) = Nothing

    Public Sub unhandledException(ByVal ex As Exception)
        shutdown()
    End Sub

    Friend unhandledExceptionHandler As UnhandledExceptionDelegate = AddressOf unhandledException

    Public Sub startService()
        If server Is Nothing Then
            server = New httpServer
        Else
            server.clearprefix()
        End If
        Dim port As Int32
        port = config.parameter(configNaming.firstpage.name _
                                , configNaming.firstpage.port _
                                , configNaming.defaultValue.firstpage.port)
        server.addport(port)
        server.start()

        raiseError("server has been started on port " + Convert.ToString(port))
    End Sub

    Public Sub shutdownservice()
        If Not server Is Nothing Then
            server.stop()
        End If
    End Sub

    Public Sub shutdown()
        shutdownService()
        consoleExtHandleFinish()
        If Not config Is Nothing Then
            config.close()
        End If
        errorHandle.finalize()
        forceQuit(0)
    End Sub

    Public Sub monitor()
        While Not consoleExtSignal() AndAlso (config.configRefreshing() OrElse server.health())
            sleep()
        End While
        shutdown()
    End Sub

    Public Sub main(ByVal args() As String)
        errorHandle.initial(defaultLogFilename())
        If Not isdebugmode() Then
            errorHandle.skipErrorType += errorHandle.errorTypeChar(errorHandle.errorType.application)
        End If
        If Not isdebugmode() Then
            registerUnhandledException(unhandledExceptionHandler)
        End If
        destructor.start()
        registerConsoleExtHandle()

        config = New configMonitor
        Dim configfile As String = Nothing
        If args.Length() > 0 Then
            configfile = args(0)
        Else
            configfile = defaultConfigfile
        End If

        assert(config.open(configfile), "cannot open configuration file " + configfile)
        responseBuffer = New pool(Of MemoryStream)

        startService()
        monitor()
    End Sub

    Private Sub config_ConfigChanged() Handles config.ConfigChanged
        raiseError("caught configuration changed, will restart service.")
        shutdownService()
        startService()
    End Sub

    Public Sub processErrorContext(ByRef context As HttpListenerContext)
        context.Response.StatusCode = HttpStatusCode.NotFound
        context.Response.StatusDescription = "NOTFOUND"
    End Sub

    Private Sub server_receive(ByVal context As HttpListenerContext) Handles server.receive
        On Error Resume Next

        Dim buff As MemoryStream = Nothing
        Dim index As Int64 = 0
        If responseBuffer.getfree(index, buff) Then
            Dim doc As xmlcontrol = Nothing
            doc = xhtmlctrl.unittests.firstpage(buff)

            If Not doc.render() Then
                raiseError("cannot render document.", errorHandle.errorType.exclamation)
            End If

            context.Response.ContentEncoding = encoding.utf8
            context.Response.ContentLength64 = buff.Position()
            context.Response.ContentType = network.http.contentType.texthtmlUtf8
            context.Response.Headers.Add(HttpResponseHeader.Server, applicationSign())
            context.Response.OutputStream.Write(buff.GetBuffer, 0, buff.Position)
            buff.Position = 0
            responseBuffer.release(index)
        Else
            raiseError("cannot get free responseBuffer, ignore request.", errorHandle.errorType.exclamation)
            processErrorContext(context)
        End If
    End Sub
End Module
